package com.googlecode.genproject.service.impl;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.DecimalFormat;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import com.googlecode.genproject.common.FileUtil;
import com.googlecode.genproject.service.GenProjectService;
import com.googlecode.genproject.service.base.ServiceSupport;

/**
 * 生成项目文件实现类
 * @author devilishking
 *
 */
public class GenProjectServiceImpl extends ServiceSupport<GenProjectServiceImpl> 
								   implements GenProjectService {
	/**
	 * 要替换的键值组
	 */
	private String[] replaceKeys = new String[]{ "demo", "Demo" };
	
	/**
	 * 生成项目文件
	 * @param properties 系统属性
	 * @throws Exception
	 */
	public void genProject(Properties properties) throws Exception{
		String projectName = "";
		String projectPath = "";
		try{
			projectName = inputStr("请输入项目名(第一个字母要小写): demo: ", "demo", "[a-z][A-Za-z0-9\\.]*[A-Za-z0-9]");
			projectPath = inputStr("请输入项目根路径: ") + "/" + projectName + "/";

			FileUtil.deleteDirectory(projectPath);
			FileUtil.makeDirectory(projectPath);
			
			String rawProjectLastVersion = properties.getProperty("rawproject.lastversion");
			
			String basePath = System.getProperty("user.dir");
			String rawZipPath = basePath + "/raw-project-" + rawProjectLastVersion + ".zip";
			String[] projectNameArr = new String[]{ projectName, projectName.substring(0, 1).toUpperCase() + 
																 projectName.substring(1) };

	        ZipInputStream zin = null;
	        ZipEntry ze = null;  
	        System.out.println();
	        System.out.println("正在解压raw.zip文件到目标文件夹."); 
	        try{
	        	zin = new ZipInputStream(new FileInputStream(rawZipPath));   
	        	double fileNum = 0.0;
	        	try{
		        	while(zin.getNextEntry() != null){
		        		fileNum++;
		        	}
				}
				catch(Exception e){
					throw e;
				}
				finally{
					if (zin != null) zin.close();  
				}
	        	
	        	zin = new ZipInputStream(new FileInputStream(rawZipPath)); 
	        	
		        byte[] buf=new byte[1024];   
		        BufferedOutputStream os = null;
		        double index = 0.0;
	    	    DecimalFormat format = new DecimalFormat("##0.00"); 
	    	    int maxLength = 0;
	    	    StringBuilder spaceStr = new StringBuilder();
		        while((ze=zin.getNextEntry()) != null){  
		        	try{
		        		index++;
		        		String loadingStr = new StringBuilder().append("解压进度: ")
															   .append(format.format(index / fileNum * 100.0))
															   .append("% (正在解压文件: ")
															   .append(ze.getName())
															   .append(")\r").toString();
		        		if (loadingStr.length() > maxLength){
		        			for(int i = maxLength; i < loadingStr.length(); i++){
		        				spaceStr.append("  ");
		        			}
		        			maxLength = loadingStr.length();
		        		}
		    	        System.out.print(new StringBuilder().append(spaceStr).append("\r"));
		    	        System.out.print(loadingStr);
		        		File file = getFile(projectPath, ze.getName(), projectNameArr);
		        		if (file.isDirectory()) continue;
			            os = new BufferedOutputStream(new FileOutputStream(file));   
			            int readLen = 0;   
			            String[] filePahtArr = file.getPath().split("\\.");
				        String fileType = filePahtArr[filePahtArr.length-1];
				        if ("java".equals(fileType) || "log".equals(fileType) 
				        							|| "xml".equals(fileType) 
				        							|| "sql".equals(fileType)){
				        	StringBuilder content = new StringBuilder();
					        while ((readLen=zin.read(buf, 0, 1024))!=-1){  
					          	content.append(new String(buf, 0, readLen));
					        }
					        os.write(content.toString().replace(replaceKeys[0], projectNameArr[0])
					        						   .replace(replaceKeys[1], projectNameArr[1])
									    			   .getBytes());
			            }
			            else{
				            while ((readLen=zin.read(buf, 0, 1024))!=-1){   
				                os.write(buf, 0, readLen);   
				            }   
			            }
		    	        System.out.print(new StringBuilder().append(spaceStr).append("\r"));
		        	}
		        	catch(Exception e){
		        		throw e;
		        	}
		        	finally{
			            if (os != null) os.close();  
		        	} 
		        } 
			}
			catch(Exception e){
				throw e;
			}
			finally{
				if (zin != null) zin.close();  
			}
	        System.out.println();
	        System.out.println(String.format("[%1$s]项目已生成.", projectName)); 
		}
		catch(Exception e){
			if (projectPath.trim().length() > 0) FileUtil.deleteDirectory(projectPath);
			throw e;
		}
	}
	
	/**
	 * 获取解压空文件/文件夹
	 * @param baseDir		  根目录
	 * @param zipFileName	  压缩文件/文件夹名
	 * @param projectNameArr 项目名组
	 * @return
	 * @throws Exception
	 */
    private File getFile(String baseDir, String zipFileName, String[] projectNameArr) throws Exception{   
    	zipFileName = zipFileName.replace(replaceKeys[0], projectNameArr[0])
    							 .replace(replaceKeys[1], projectNameArr[1]);
    	File file = new File(baseDir + zipFileName);
    	if (file.isDirectory() || zipFileName.lastIndexOf("/") == zipFileName.length()-1){
    		file.mkdirs();
    	}
    	else{
    		file.getParentFile().mkdirs();
    		file.createNewFile();
    	}
        return file;   
    }   
}